package com.distribute.framework.core.lang;

import com.distribute.framework.core.web.helper.Utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public abstract class ScriptJava {
	private Map<String,Object> variables = new HashMap();
	public abstract  Integer getId();
	public abstract Object execute(Object... args);
	public Map<String, Object> getVariables() {
		return variables;
	}
	
	
	/**
	 * 执行脚本
	 * @param classname
	 * @param javaCode
	 * @param imports
	 * @param args
	 * @return
	 * @throws Exception 
	 */
	public static Object execute(String classname,String javaCode,String[] imports,Object... args) throws Exception{
		ScriptJava script = create(classname,javaCode,imports);
		return script.execute(args);
	}
	
	//缓存同名类
	private static Map<String,Class> scriptclasses = new HashMap();
	
	private static String javac="\"" + Utils.or(Utils.config("JAVA_HOME"),System.getenv("JAVA_HOME")) + File.separator + "bin" + File.separator + ((System.getProperties().getProperty("os.name").toLowerCase().startsWith("win"))?("javac.exe\""):("javac\""));
	public static ScriptJava create(String classname,String javacode,String[] imports) throws Exception{
		//代码hashcode
		Integer id = javacode.hashCode();
		//比对代码是否相同，如果相同，则返回之前的类
		Class scriptClass = scriptclasses.get(classname);
		if(scriptClass!=null){
			ScriptJava scriptJava = (ScriptJava) scriptClass.newInstance();
			if(scriptJava.getId().intValue()==id.intValue())
				return scriptJava;
		}
		//对应的类名
		String className="scripts."+classname;
		//获取对应的java文件
		String filePath=className.replaceAll("\\.", File.separator);
		//根目录
		String root=URLDecoder.decode(Thread.currentThread().getContextClassLoader().getResource("/").getPath(),"UTF-8");
		//lib目录
		String lib = new File(root).getParentFile().getAbsolutePath()+File.separator+"lib";
		//如果系统配置文件配置了路径，则以配置的库
		if(!Utils.empty(Utils.config("lib")))
			lib = Utils.config("lib");
		
		//原代码新代码
		String javaCode = Utils.trim(javacode);
		javaCode = getVarNames(javaCode);
		//局部变量列表
		/*List<String> varnames = getVarNames(javaCode);
		String varCodes = "\r\n";
		for(String varname:varnames){
			varCodes+="			super.getVariables().put(\""+varname+"\","+varname+");\r\n";
		}
		if(Pattern.compile("[;]?([\\s]{0,}return)").matcher(javaCode).find())
			javaCode = javaCode.replaceAll("([;]?)([\\s]{0,}return)","$1"+ varCodes.replace("$", "\\$")+"$2");
		else
			javaCode+=varCodes;*/
		//需要引用的包
		String strImports = "";
		if(imports!=null){
			for(String str:imports){
				strImports+="import "+str+";\r\n";
			}
		}
		
		//脚本代码模版
		String template = Utils.readFile(ScriptJava.class.getResourceAsStream("ScriptJava"), Utils.UTF8);
		template = template.replace("{package}", className.substring(0, className.lastIndexOf(".")));
		template = template.replace("{import}", strImports);
		template = template.replace("{class}", className.substring(className.lastIndexOf(".")+1));
		template = template.replace("{code}", javaCode);
		template = template.replace("{id}", ""+id);
		//写java文件
		Utils.writeFile(root+filePath+".java", template, Utils.UTF8);
		
		String strOrder=javac+" -encoding UTF-8 -classpath \""+root+"\" -extdirs \""+lib+"\" \""+root+filePath+ ".java\"";
		System.out.println(strOrder);
		final Process process = Runtime.getRuntime().exec(new String[]{ "sh", "-c", strOrder });
		InputStream input = process.getErrorStream();
		BufferedReader reader=new BufferedReader(new InputStreamReader(input));
		String strLine=null;
		String strError = "";
		while((strLine=reader.readLine())!=null)
			strError+="\r\n"+strLine;
		if(!Utils.empty(strError))
			throw new Exception(strError);
		
		ScriptClassLoader classLoader = new ScriptClassLoader(root);
		Class clazz = classLoader.getClass(className);
		scriptclasses.put(classname, clazz);
		ScriptJava scriptJava = (ScriptJava) clazz.newInstance();
		return scriptJava;
	}
	
	/**
	 * 获取局部变量名称列表
	 */
	private static String getVarNames(String javaCode){
		/*String code = javaCode;
		code = code.replace("\\\"", "");
		code = code.replace("\\(", "");
		code = code.replace("\\)", "");
		code = code.replaceAll("\"[^\"]{0,}\"", "#");
		code = code.replace(";", ";\r\n");
		code = code.replaceAll("<[^>]+>", "");
		code  = code.replaceAll("//[^\\n^\\r]+", "");//去除注释
		code  = code.replaceAll("\\)[\\s]{0,}", ")");*/
		/*while(Pattern.compile("\\{[^\\}^\\{]+\\}").matcher(code).find())
			code = code.replaceAll("\\{[^\\}^\\{]+\\}", "");*/
		List<String> vars=new ArrayList();
		Matcher match = Pattern.compile("^([\\s]{0,})([$_a-zA-Z][$_a-zA-Z0-9\\.]{0,})(<[$_a-zA-Z][$_a-zA-Z0-9]{0,}>)?([\\s]{1,})([$_a-zA-Z][$_a-zA-Z0-9]{0,})[\\s|=|;][\\s\\S]*?$",Pattern.MULTILINE).matcher(javaCode);
		String key = "return|public|abstract|assert|break|case|catch|const|continue|default|do|else|enum|extends|final|finally|for|if|implements|import|instanceof|interface|native|new|package|private|protected|public|return|static|strictfp|super|switch|synchronized|this|throw|throws|transient|try|void|volatile|while";
		String word = "byte|char|double|float|int|long|short";
		String convertString = "";
		int last = 0;
		while(match.find()){
			String vBlank = match.group(1);
			String vType = match.group(2);
			String vName = match.group(5);
			convertString+=javaCode.substring(last,match.start(1));			
			convertString+=match.group();
			if(!Pattern.matches(key, vType)&&!Pattern.matches(key, vName)&&!Pattern.matches(word, vName)){
				convertString+="\r\n"+vBlank+"super.getVariables().put(\""+vName+"\","+vName+");";
			}
			last = match.end(0);
		}
		convertString+=javaCode.substring(last,javaCode.length());	
		return convertString;
	}
	
	
	public static void main(String...strings) throws Exception{
		System.out.println(getVarNames(Utils.readFile("f://9.txt")));
	}

	
	
}